#ifndef __CM_NAT_SEARCH_CLIENT_H__
#define __CM_NAT_SEARCH_CLIENT_H__

#include "MulticastPort.h"
#include "StunMessage.h"
#include "cm_base/BaseTimer.h"
#include "cm_base/ByteBuffer.h"
#include "cm_base/ByteBufferPool.h"
#include "Poco/Net/SocketReactor.h"

namespace cm_nat
{
    class SearchClient;

    typedef struct SearchDaemonInfoStruct 
    {
        SocketAddress sa;
        std::string username;
    }SearchDaemonInfo;

    class SearchClientListener
    {
    public:
        virtual void onSearchFinish( SearchClient* client ) = 0;
        virtual void onAuthResult( SearchClient* client, int result ) = 0;
    };

    //Multicast desired camera's info in LAN
    //specify camera will echo if exist
    class SearchClient: public MulticastPortListener, public BaseTimerListener
    {
    public:
        SearchClient( ByteBufferPool* p_pool, SocketReactor* reactor, BaseTimer* p_timer );
        ~SearchClient();

        int setup(IPAddress bindIP);
        int teardown();

        void registerListener( SearchClientListener* p_listener );

        void setMediaAddress( SocketAddress mediaAddress );

        int startSearch();
        int authenticate( std::string username, std::string pwd );

        bool detectMessage(ByteBuffer* data);
        int processMessage( ByteBuffer* data );

        int processSearchResponse( StunMessage* p_sm, const SocketAddress& from );
        int processAuthResponse( StunMessage* p_sm, const SocketAddress& from );

        //from MulticastPortListener
        void onReceive(MulticastPort*p_port, ByteBuffer* p_data);
        //from BaseTimerListener
        void onTimer(TimerNotification* p_tn ); 

        void startTimer(long interval, UInt32 context);
        enum
        {
            TIMER_SEARCH_DAEMON
        };
        enum
        {
            AUTH_RES_FAIL,
            AUTH_RES_SUCCESS
        };


    protected:
        const SearchDaemonInfo* findDaemon( std::string username );

    protected:
        ByteBufferPool* m_bufferPool;
        SocketReactor* m_reactor;
        BaseTimer* m_timer;

        MulticastPort* m_port;

        SearchClientListener* m_listener;

        typedef std::list< SearchDaemonInfo* > SearchDaemonList;
        SearchDaemonList m_foundDaemons;

        const SearchDaemonInfo* m_connectDaemon;

        SocketAddress m_clientMediaAddress;
        SocketAddress m_daemonMediaAddress;
    };
}

#endif